#!/bin/bash
# 功能：清理Kubernetes集群，各节点需分别执行脚本。
# 来源：网络收集、AI完善

# 用法：curl -sSL https://gitee.com/veryx/galaxy-tools/raw/master/1-k8s/k8s_cleanup.sh | sudo bash



# 检查root权限
if [ "$(id -u)" -ne 0 ]; then
  echo "请使用 sudo 运行此脚本！"
  exit 1
fi

# 初始化配置
LOG_FILE="/var/log/k8s_cleanup_$(date +%Y%m%d_%H%M%S).log"
exec > >(tee -a "$LOG_FILE") 2>&1

# 颜色定义
N='\033[0m'
R='\033[0;31m'
B='\033[0;34m'
G='\033[0;32m'
Y='\033[1;33m'

# 状态跟踪
declare -A RESULTS
TOTAL_STEPS=0
FAILED_STEPS=0
SUCCESS_STEPS=0
SKIPPED_STEPS=0
WARNINGS=0

# 系统信息
OS_TYPE=""
OS_VERSION=""
PKG_MANAGER=""
REMOVE_CMD=""

# 函数：带状态显示的步骤执行
run_step() {
  local step_name=$1
  local step_cmd=$2
  local category=$3

  ((TOTAL_STEPS++))
  echo -e "\n[$(date +'%Y-%m-%d %H:%M:%S')] ${B}[+]${N} 执行: ${step_name}..."

  local exit_code=0
  local temp_err=$(mktemp)
  {
    eval "$step_cmd" 2>&1 | tee -a "$LOG_FILE" 1>&2
    exit_code=${PIPESTATUS[0]}
  } 2> "$temp_err"
  local error_msg=$(<"$temp_err")
  rm -f "$temp_err"

  if [ $exit_code -eq 0 ]; then
    echo -e "${G}√ 成功${N}"
    RESULTS["$category/$step_name"]="成功"
    ((SUCCESS_STEPS++))
    return 0
  else
    echo -e "${R}× 失败${N}"
    RESULTS["$category/$step_name"]="失败: \n${error_msg}"
    ((FAILED_STEPS++))
    return 1
  fi
}

# 函数：跳过步骤
skip_step() {
  local step_name=$1
  local reason=$2
  local category=$3

  ((TOTAL_STEPS++))
  echo -e "\n[$(date +'%Y-%m-%d %H:%M:%S')] ${Y}[~]${N} 跳过: ${step_name} (原因: ${reason})"
  RESULTS["$category/$step_name"]="跳过: $reason"
  ((SKIPPED_STEPS++))
}

# 函数：警告记录
add_warning() {
  local warning_msg=$1
  ((WARNINGS++))
  echo -e "${Y}[!] 警告: ${warning_msg}${N}"
}

# 函数：检测系统信息
detect_system() {
  echo -e "${B}======== 系统检测 ========${N}"

  if [ -f /etc/os-release ]; then
    . /etc/os-release
    OS_TYPE="$ID"
    OS_VERSION="$VERSION_ID"
    echo -e "检测到系统: ${OS_TYPE} ${OS_VERSION}"

    case $OS_TYPE in
      ubuntu|debian|linuxmint)
        PKG_MANAGER="apt-get"
        REMOVE_CMD="apt-get purge -y"
        ;;
      centos|rhel|rocky|kylin|almalinux)
        if [[ "$OS_VERSION" == 8* ]]; then
          PKG_MANAGER="dnf"
          REMOVE_CMD="dnf remove -y"
        else
          PKG_MANAGER="yum"
          REMOVE_CMD="yum remove -y"
        fi
        ;;
      *)
        if command -v dnf &>/dev/null; then
          PKG_MANAGER="dnf"
          REMOVE_CMD="dnf remove -y"
        elif command -v yum &>/dev/null; then
          PKG_MANAGER="yum"
          REMOVE_CMD="yum remove -y"
        elif command -v apt-get &>/dev/null; then
          PKG_MANAGER="apt-get"
          REMOVE_CMD="apt-get purge -y"
        else
          add_warning "无法确定包管理器，将跳过软件包移除步骤"
          PKG_MANAGER="echo '[跳过]'"
          REMOVE_CMD="echo '[跳过]'"
        fi
        ;;
    esac
  else
    add_warning "无法检测系统类型，使用通用清理方式"
    if command -v apt-get &>/dev/null; then
      PKG_MANAGER="apt-get"
      REMOVE_CMD="apt-get purge -y"
    elif command -v dnf &>/dev/null; then
      PKG_MANAGER="dnf"
      REMOVE_CMD="dnf remove -y"
    elif command -v yum &>/dev/null; then
      PKG_MANAGER="yum"
      REMOVE_CMD="yum remove -y"
    else
      PKG_MANAGER="echo '[跳过]'"
      REMOVE_CMD="echo '[跳过]'"
    fi
  fi

  echo -e "使用包管理器: ${PKG_MANAGER}\n"
}

# 函数：获取当前用户
get_current_user() {
    local user=""
    
    # 优先级1: SUDO_USER (最可靠)
    if [ -n "$SUDO_USER" ] && [ "$SUDO_USER" != "root" ]; then
        user="$SUDO_USER"
        echo "$user"
        return 0
    fi
    
    # 优先级2: 当前登录用户
    if command -v who &>/dev/null; then
        user=$(who am i | awk '{print $1}' 2>/dev/null)
        if [ -n "$user" ] && [ "$user" != "root" ]; then
            echo "$user"
            return 0
        fi
    fi
    
    # 优先级3: 环境变量
    if [ -n "$USER" ] && [ "$USER" != "root" ]; then
        user="$USER"
        echo "$user"
        return 0
    fi
    
    # 如果都无法确定，返回空字符串
    echo ""
    return 1
}

# 函数：确认操作
confirm_operation() {
  echo -e "${R}[!] 警告：本脚本将永久删除Kubernetes集群及相关数据！${N}"
  echo -e "${R}[!] 包括: kubeadm, kubelet, kubectl, CNI插件, containerd等${N}\n"
  read -p "确认继续操作？(y/N) " -n 1 -r < /dev/tty
  echo
  if [[ ! $REPLY =~ ^[Yy]$ ]]; then
    echo -e "${G}操作已取消${N}"
    exit 0
  fi
}

# 模块：集群节点清理
clean_cluster_nodes() {
  echo -e "\n${B}======== 集群节点清理 ========${N}"

  if command -v kubectl &>/dev/null && [ -f ~/.kube/config ]; then
    NODE_NAME=$(hostname)
    run_step "驱逐节点 $NODE_NAME" "kubectl drain $NODE_NAME --delete-emptydir-data --force --ignore-daemonsets 2>/dev/null || true" "集群操作"
    run_step "从集群删除节点" "kubectl delete node $NODE_NAME 2>/dev/null || true" "集群操作"
  else
    skip_step "驱逐和删除节点" "kubectl未安装或未配置" "集群操作"
  fi
}

# 模块：核心组件清理
clean_core_components() {
  echo -e "\n${B}======== 核心组件清理 ========${N}"

  # 重置kubeadm
  if command -v kubeadm &>/dev/null; then
    run_step "重置kubeadm" "kubeadm reset --force" "核心组件"
  else
    skip_step "重置kubeadm" "kubeadm未安装" "核心组件"
  fi

  # 停止Kubernetes服务
  k8s_services=("kubelet" "kube-scheduler" "kube-controller-manager" "kube-apiserver" "kube-proxy")
  for svc in "${k8s_services[@]}"; do
    if systemctl list-unit-files | grep -q "$svc"; then
      run_step "停止服务 $svc" "systemctl stop $svc 2>/dev/null || true" "服务管理"
      run_step "禁用服务 $svc" "systemctl disable $svc 2>/dev/null || true" "服务管理"
    else
      skip_step "停止服务 $svc" "服务不存在" "服务管理"
    fi
  done

  # 清理kubelet
  kubelet_items=(
    "删除kubelet数据目录" "rm -rf /var/lib/kubelet/"
    "删除kubelet服务文件" "rm -rf /etc/systemd/system/kubelet.service /etc/systemd/system/kubelet.service.d/"
    "删除kubernetes配置" "rm -rf /etc/kubernetes/"
  )

  for ((i=0; i<${#kubelet_items[@]}; i+=2)); do
    step_name="${kubelet_items[i]}"
    step_cmd="${kubelet_items[i+1]}"
    run_step "$step_name" "$step_cmd" "K8s组件"
  done

  # 卸载k8s命令行工具
  k8s_pkgs=("kubeadm" "kubectl" "kubelet" "kubernetes-cni")
  for pkg in "${k8s_pkgs[@]}"; do
    run_step "卸载软件包 $pkg" "$REMOVE_CMD $pkg 2>/dev/null || true" "软件包清理"
  done

  # 删除二进制文件
  binaries=("kubelet" "kubectl" "kubeadm" "crio" "crictl" "runc" "containerd" "containerd-shim" "flanneld")
  for bin in "${binaries[@]}"; do
    if [ -f "/usr/bin/$bin" ] || [ -f "/usr/local/bin/$bin" ]; then
      run_step "删除二进制文件 $bin" "rm -f /usr/bin/$bin /usr/local/bin/$bin 2>/dev/null || true" "二进制文件清理"
    else
      skip_step "删除二进制文件 $bin" "文件不存在" "二进制文件清理"
    fi
  done
}

# 模块：网络清理
clean_network() {
  echo -e "\n${B}======== 网络清理 ========${N}"

  # 清理CNI网络接口
  cni_interfaces=("flannel.1" "cni0" "docker0" "weave" "calico")
  for iface in "${cni_interfaces[@]}"; do
    if ip link show "$iface" &>/dev/null; then
      run_step "删除网络接口 $iface" "ip link delete $iface 2>/dev/null || true" "网络清理"
    else
      skip_step "删除网络接口 $iface" "接口不存在" "网络清理"
    fi
  done

  # 清理CNI配置和插件
  run_step "删除CNI配置" "rm -rf /etc/cni/net.d/ 2>/dev/null || true" "网络清理"
  run_step "删除CNI插件" "rm -rf /opt/cni/bin/ 2>/dev/null || true" "网络清理"

  # 清理网络规则
  network_commands=(
    "iptables -F"
    "iptables -X"
    "iptables -t nat -F"
    "iptables -t nat -X"
    "iptables -t mangle -F"
    "iptables -t mangle -X"
    "iptables -P INPUT ACCEPT"
    "iptables -P OUTPUT ACCEPT"
    "iptables -P FORWARD ACCEPT"
  )

  for cmd in "${network_commands[@]}"; do
    run_step "网络规则: $cmd" "$cmd 2>/dev/null || true" "网络清理"
  done

  # 清理IPVS
  if command -v ipvsadm &>/dev/null; then
    run_step "清理IPVS表" "ipvsadm --clear" "网络清理"
  else
    skip_step "清理IPVS表" "ipvsadm未安装" "网络清理"
  fi

  # 清理特定CNI插件
  if [ -d "/opt/replicated" ]; then
    run_step "删除replicated目录" "rm -rf /opt/replicated" "特定组件"
  fi

  if [ -d "/etc/coredns" ]; then
    run_step "删除CoreDNS配置" "rm -rf /etc/coredns" "特定组件"
  fi

  if [ -d "/opt/kurl" ]; then
    run_step "删除kurl目录" "rm -rf /opt/kurl" "特定组件"
  fi
}

# 模块：容器运行时清理
clean_container_runtime() {
  echo -e "\n${B}======== 容器运行时清理 ========${N}"

  # 清理所有正在运行的容器
  if command -v crictl &>/dev/null; then
    run_step "列出所有容器" "crictl ps -a" "容器清理"
    run_step "停止所有容器" "crictl ps -q | xargs -r crictl stop 2>/dev/null || true" "容器清理"
    run_step "删除所有容器" "crictl rm -fa 2>/dev/null || true" "容器清理"
    run_step "删除所有镜像" "crictl rmi --prune 2>/dev/null || true" "容器清理"
  else
    skip_step "清理crictl容器和镜像" "crictl未安装" "容器清理"
  fi

  # 清理docker
  if command -v docker &>/dev/null; then
    run_step "停止Docker容器" "docker ps -aq | xargs -r docker stop 2>/dev/null || true" "容器清理"
    run_step "删除Docker容器" "docker ps -aq | xargs -r docker rm -f 2>/dev/null || true" "容器清理"
    run_step "删除K8s相关镜像" "docker images | grep 'k8s.io/' | awk '{print \$3}' | xargs -r docker rmi 2>/dev/null || true" "容器清理"
    run_step "清理容器网络" "docker network prune -f 2>/dev/null || true" "容器清理"
  else
    skip_step "清理Docker容器和镜像" "docker未安装" "容器清理"
  fi

  # 清理containerd
  containerd_items=(
    "停止containerd服务" "systemctl stop containerd 2>/dev/null || true"
    "禁用containerd服务" "systemctl disable containerd 2>/dev/null || true"
    "删除containerd数据目录" "rm -rf /var/lib/containerd"
    "删除containerd配置" "rm -rf /etc/containerd"
    "删除containerd运行时文件" "rm -rf /run/containerd"
    "卸载containerd软件包" "$REMOVE_CMD containerd containerd.io 2>/dev/null || true"
  )

  for ((i=0; i<${#containerd_items[@]}; i+=2)); do
    step_name="${containerd_items[i]}"
    step_cmd="${containerd_items[i+1]}"
    run_step "$step_name" "$step_cmd" "容器运行时"
  done
}

# 模块：etcd清理
clean_etcd() {
  echo -e "\n${B}======== etcd清理 ========${N}"

  etcd_items=(
    "停止etcd服务" "systemctl stop etcd 2>/dev/null || true"
    "禁用etcd服务" "systemctl disable etcd 2>/dev/null || true"
    "卸载etcd软件包" "$REMOVE_CMD etcd 2>/dev/null || true"
    "删除etcd数据目录" "rm -rf /var/lib/etcd/"
    "删除etcd配置" "rm -rf /etc/etcd/"
  )

  for ((i=0; i<${#etcd_items[@]}; i+=2)); do
    step_name="${etcd_items[i]}"
    step_cmd="${etcd_items[i+1]}"
    run_step "$step_name" "$step_cmd" "etcd"
  done
}

# 模块：配置文件清理
clean_config_files() {
  echo -e "\n${B}======== 配置文件清理 ========${N}"

  # 获取当前用户信息
  CURRENT_USER=$(get_current_user)

  # 清理kubeconfig文件
  kube_users=(
    "root" "/root/.kube"
    "galaxyship" "/home/galaxyship/.kube"
  )
  if [ -n "$CURRENT_USER" ]; then
    kube_users+=("$CURRENT_USER" "/home/$CURRENT_USER/.kube")
  fi

  for ((i=0; i<${#kube_users[@]}; i+=2)); do
    user="${kube_users[i]}"
    kube_dir="${kube_users[i+1]}"

    if [ -d "$kube_dir" ]; then
      run_step "删除$user用户的kubeconfig" "rm -rf \"$kube_dir\"" "kubeconfig清理"
    else
      skip_step "删除$user用户的kubeconfig" "$kube_dir目录不存在" "kubeconfig清理"
    fi
  done

  # 查找并清理其他.kube目录
  echo -e "${Y}[检查]${N} 查找系统中其他可能的.kube目录..."
  other_kube_dirs=$(find /home -name ".kube" -type d 2>/dev/null)
  if [ -n "$other_kube_dirs" ]; then
    for dir in $other_kube_dirs; do
      user=$(echo $dir | cut -d/ -f3)
      run_step "删除$user用户的kubeconfig" "rm -rf \"$dir\"" "kubeconfig清理"
    done
  else
    echo -e "${G}[√] 未发现其他用户的.kube目录${N}"
  fi

  # 清理临时文件和socket
  socket_patterns=(
    "*kube*"
    "*kubelet*"
    "*flannel*"
    "*cni*"
    "*containerd*"
    "*etcd*"
  )

  for pattern in "${socket_patterns[@]}"; do
    run_step "清理socket文件 $pattern" "find /var/run/ /run/ -name '$pattern' -exec rm -rf {} \\; 2>/dev/null || true" "临时文件清理"
  done

  # 清理sysctl配置
  if [ -f /etc/sysctl.d/k8s.conf ]; then
    run_step "删除K8s sysctl配置" "rm -f /etc/sysctl.d/k8s.conf" "系统配置"
  else
    skip_step "删除K8s sysctl配置" "文件不存在" "系统配置"
  fi

  # 清理/etc/prfiles文件额外内容
  profile_cleanup_lines=(
    'export KUBECONFIG=/etc/kubernetes/admin.conf'
    'if  type _init_completion >/dev/null 2>&1; then source <(kubectl completion bash); fi'
  )

  for line in "${profile_cleanup_lines[@]}"; do
    escaped_line=$(sed 's/[^^]/[&]/g; s/\^/\\^/g' <<< "$line")
    if grep -qF "$line" /etc/profile; then
      sed -i "\|^${escaped_line}$|d" /etc/profile
    fi
  done
}

# 模块：系统服务清理
clean_system_services() {
  echo -e "\n${B}======== 系统服务清理 ========${N}"

  run_step "重载systemd" "systemctl daemon-reload && systemctl reset-failed" "系统服务"
  run_step "清理swap" "swapoff -a" "系统配置"
}

# 模块：验证清理结果
verify_cleanup() {
  echo -e "\n${B}======== 验证清理结果 ========${N}"

  # 检查残留目录
  check_dirs=(
    "/opt/kurl"
    "/opt/cni/bin"
    "/etc/coredns"
    "/etc/cni/net.d"
    "/etc/containerd"
    "/etc/kubernetes"
    "/var/lib/kurl"
    "/var/lib/etcd"
    "/var/lib/kubelet"
    "/var/lib/containerd"
    "/var/run/kubernetes"
  )

  for dir in "${check_dirs[@]}"; do
    if [ -d "$dir" ]; then
      echo -e "${Y}[!]${N} 残留目录: $dir"
      run_step "强制删除残留目录 $dir" "rm -rf \"$dir\"" "残留清理"
    else
      echo -e "${G}[√] 已清理: $dir${N}"
    fi
  done

  # 检查残留进程
  check_procs=("kubelet" "kube-proxy" "kube-apiserver" "etcd" "containerd" "flanneld")
  found_procs=0

  for proc in "${check_procs[@]}"; do
    if pgrep -f "$proc" > /dev/null; then
      proc_pid=$(pgrep -f "$proc")
      echo -e "${R}[!] 残留进程: $proc (PID: $proc_pid)${N}"
      run_step "强制终止进程 $proc" "pkill -9 -f $proc 2>/dev/null || true" "进程清理"
      found_procs=1
    fi
  done

  if [ $found_procs -eq 0 ]; then
    echo -e "${G}[√] 未发现残留进程${N}"
  fi
}

# 模块：显示清理结果
show_results() {
  echo -e "\n${B}======== 清理结果汇总 ========${N}"
  echo -e "总步骤: ${TOTAL_STEPS}"
  echo -e "${G}成功: ${SUCCESS_STEPS}${N}"
  echo -e "${Y}跳过: ${SKIPPED_STEPS}${N}"
  echo -e "${R}失败: ${FAILED_STEPS}${N}"

  if [ $WARNINGS -gt 0 ]; then
    echo -e "${Y}警告: ${WARNINGS}${N}"
  fi

  # 输出失败项
  if [ $FAILED_STEPS -gt 0 ]; then
    echo -e "\n${Y}[失败项明细]${N}"
    for key in "${!RESULTS[@]}"; do
      if [[ ${RESULTS[$key]} == 失败* ]]; then
        echo -e "${R}→ $key: ${RESULTS[$key]}\n${N}"
      fi
    done
  fi

  # 完成提示
  echo -e "\n详细日志已记录到: ${LOG_FILE}\n"

  if [ $FAILED_STEPS -eq 0 ]; then
    echo -e "${G}[√] Kubernetes卸载成功！${N}"
    echo -e "${Y}[!] 多服务器集群的务必每个节点都执行此脚本！${N}"
    echo -e "${Y}[!] 继续使用本服务器前请重启操作系统，命令参考: ${B}sudo reboot now${N}"
  else
    echo -e "${Y}[!] 有${R}${FAILED_STEPS}${Y}个步骤失败，建议检查并手动处理${N}"
  fi
}

# 主执行流程
main() {
  echo -e "${G}=========================================================${N}"
  echo -e "${G}       Kubernetes集群完全清理脚本 - 优化版 v3.1            ${N}"
  echo -e "${G}=========================================================${N}"

  detect_system
  confirm_operation

  # 执行各清理模块
  clean_cluster_nodes
  clean_core_components
  clean_network
  clean_container_runtime
  clean_etcd
  clean_config_files
  clean_system_services
  verify_cleanup

  show_results
}

main "$@"